/**
 * @author zdz8207
 * 通用面向对象脚本库
 * @version 1.0
 * 
 */
var coos = function(){this.version = "1.0";};

/**
 * 创建对象和方法的通用函数，兼容多种浏览器，实现高效、方便的继承体系，解决多种常规创建的性能问题
 * @param parantObj jsonObj
 * @example 
 * var Person = coos.Class      //默认派生自object基本类
({
    Create: function(name, age)
    {
        this.base();    //调用上层构造函数
        this.name = name;
        this.age = age;
    },
    SayHello: function()
    {
        alert("Hello, I'm " + this.name + ", " + this.age + " years old.");
    },
    toString: function()    //覆写toString方法
    {
        return this.name;
    }
});

var Employee = coos.Class(Person,    //派生自Person类
{
    Create: function(name, age, salary)
    {
        this.base(name, age);  //调用基类的构造函数
        this.salary = salary;
    },
    ShowMeTheMoney: function()
    {
        alert(this + " $" + this.salary); //这里直接引用this将隐式调用toString()
    }
});
var BillGates = new Person("Bill Gates", 53);
var SteveJobs = new Employee("Steve Jobs", 53, 1234);
alert(BillGates);   //这里将隐式调用覆写后的toString()方法
BillGates.SayHello();
SteveJobs.SayHello();
SteveJobs.ShowMeTheMoney();

var LittleBill = new BillGates.Type("Little Bill", 6); //用BillGate的类型建LittleBill
LittleBill.SayHello();

alert(BillGates.isA(Person));       //true
alert(BillGates.isA(Employee));     //false
alert(SteveJobs.isA(Person));       //true
* 
 */
coos.Class = function()
{
    var aDefine = arguments[arguments.length-1]; //最后一个参数是类定义
    if(!aDefine) return;
    var aBase = arguments.length>1 ? arguments[0] : coos.object; //解析基类
    
    function prototype_(){}; //构造prototype的临时函数，用于挂接原型链
    prototype_.prototype = aBase.prototype;  //准备传递prototype
    var aPrototype = new prototype_();    //建立类要用的prototype
    
    for(var member in aDefine)  //复制类定义到当前类的prototype
    {
        if(member!="Create")    //构造函数不用复制
        {
            aPrototype[member] = aDefine[member];
        }
    }
    //根据是否继承特殊属性和性能情况，可分别注释掉下列的语句
    if(aDefine.toString != Object.prototype.toString)
    {
        aPrototype.toString = aDefine.toString;
    }
    if(aDefine.toLocaleString != Object.prototype.toLocaleString)
    {
        aPrototype.toLocaleString = aDefine.toLocaleString;
    }
    if(aDefine.valueOf != Object.prototype.valueOf)
    {
        aPrototype.valueOf = aDefine.valueOf;
    }
    if(aDefine.Create)  //若有构造函数
    {
        var aType = aDefine.Create;  //类型即为该构造函数
    }
    else    //否则为默认构造函数
	{
        aType = function()
        {
            this.base.apply(this, arguments);   //调用基类构造函数
        };
	}

    aType.prototype = aPrototype;   //设置类(构造函数)的prototype
    aType.Base = aBase;             //设置类型关系，便于追溯继承关系
    aType.prototype.Type = aType;   //为本类对象扩展一个Type属性
    return aType;   //返回构造函数作为类
};

//根类object定义：
coos.object = function(){};    //定义小写的object根类，用于实现最基础的方法等
coos.object.prototype.isA = function(aType)   //判断对象是否属于某类型
{
    var self = this.Type;
    while(self)
    {
        if(self == aType) return true;
        self = self.Base;
    }
    return false;
};

coos.object.prototype.base = function()  //调用基类构造函数
{
    var Base = this.Type.Base;  //获取当前对象的基类  
    if(!Base.Base)  //若基类已没有基类
    {
        Base.apply(this, arguments);     //则直接调用基类构造函数
    }
    else    //若基类还有基类         
    {
        this.base = MakeBase(Base);     //先覆写this.base
        Base.apply(this, arguments);    //再调用基类构造函数
        delete this.base;               //删除覆写的base属性
    }
    function MakeBase(Type) //包装基类构造函数
    {
        var Base = Type.Base;
        if(!Base.Base) return Base; //基类已无基类，就无需包装
        return function()   //包装为引用临时变量Base的闭包函数
        {
            this.base = MakeBase(Base);     //先覆写this.base
            Base.apply(this, arguments);    //再调用基类构造函数
        }
    }
};
/**
 * 扩展函数功能
 * @param destination 要扩展的函数
 * @param source 扩展函数
 * @example
 coos.extend(Array.prototype,{
	clear : function () 
	{
		this.length = 0;
		return this;
	},
	first : function () 
	{
		return this[0];
	},
	last : function () 
	{
		return this[this.length - 1];
	}
});
 */
coos.extend = function(destination, source) {
  for (var property in source)
  {
    destination[property] = source[property];
  }
  return destination;
};

/**
 * simple inherit whit call parent this attribute
 * @param parentFunction
 */
coos.call = function(parentFunction)
{
	var parentfn = parentFunction + ".call(this)";
	eval(parentfn);
};

/**
 * override method
 * @param origclass, overrides the overrides is a json or hashmap
 */
coos.override = function(origclass, overrides)
{
    if(overrides)
    {
        var p = origclass.prototype;
        for(var method in overrides)
        {
            p[method] = overrides[method];
        }
    }
};

/**
 * 克隆对象
 */
coos.clone = function(obj)
{
	var temp = null;
	for(var p in obj)
	{
		temp[p] = obj[p];
	}
	return temp;
};

/**
 * 通用接口函数，为实现设计模式提供支持
 * @param name String类型 接口名称
 * @param methods 字符串数组，每个字符串都是一个必须的方法名称
 * @example 
 	//test coos.Interface 
	var testInterface = new coos.Interface("testInterface",["getId","getName"]);
	
	function adminUser(user)
	{
		//传入的user对象必须实现testInterface的方法
		coos.Interface.impl(user,testInterface);
		//由上面的接口保证了user对象实现了接口方法可以安全使用
		var id = user.getId();
		var name = user.getName();
		var message = "I'm a admin user";
		alert("id = " + id + " name = " + name + " message = " + message);
	}
	
	function vipUser(user)
	{
		//传入的user对象必须实现testInterface的方法
		coos.Interface.impl(user,testInterface);
		//由上面的接口保证了user对象实现了接口方法可以安全使用
		var id = user.getId();
		var name = user.getName();
		var message = "I'm a vip user";
		alert("id = " + id + " name = " + name + " message = " + message);
	}
	
	function user(id,name)
	{
		this.getId = function(){return id};
		this.getName = function(){return name};
	}
	
	adminUser(new user("1","admin"));
	vipUser(new user("2","zdz"));
 * 
 */
coos.Interface = function(name, methods) {
    if(arguments.length != 2) {
        throw new Error("Interface constructor called with " + arguments.length + "arguments, but expected exactly 2.");
    }
    
    this.name = name;
    this.methods = [];
    for(var i = 0, len = methods.length; i < len; i++) {
        if(typeof methods[i] !== 'string')
        {
            throw new Error("Interface constructor expects method names to be " + "passed in as a string.");
        }
        this.methods.push(methods[i]);        
    }    
};

/**
 * 最少传入两个参数，一个为对象，另外为要实现的接口，可传入多个接口
 * 在使用接口方法前作判断coos.Interface.impl(user,testInterface);
 */
coos.Interface.impl = function(object) {
    if(arguments.length < 2) {
        throw new Error("Function Interface.impl called with " + 
          arguments.length  + "arguments, but expected at least 2.");
    }

    for(var i = 1, len = arguments.length; i < len; i++) 
    {
        var _interface = arguments[i];
        if(_interface.constructor !== coos.Interface)
        {
            throw new Error("Function Interface.impl expects arguments "   
              + "two and above to be instances of Interface.");
        }
        
        for(var j = 0, methodsLen = _interface.methods.length; j < methodsLen; j++)
        {
            var method = _interface.methods[j];
            if(!object[method] || typeof object[method] !== 'function')
            {
                throw new Error("Function Interface.impl: object " 
                  + "does not implement the " + _interface.name 
                  + " interface. Method " + method + " was not found.");
            }
        }
    } 
};

/**
 * 反射机制的简单实现
 * @param obj 传入对象为obj类型,可以是json形式的
 * 
 */
coos.reflection = function(obj)
{
	for(var p in obj)
	{
		if(typeof(obj[p]) == "function")
		{
			//如果属性为function类型则执行
			obj[p]();
		}
	}
};

/**
 * 利用闭包构造一个单例类型返回，不能创建新的实例
 * @param fn 闭包函数function(){}的形式
 * @param singletonName 创建的单例类型名称
 * @example
	 var sessionFactory = new coos.singleton(
		function(){
			this.message = "I'm a sessionFactory!";
			this.sayHello = function(){alert("Hello!");}
		},"sessionFactory"
	);
	var mySession = sessionFactory.getInstance();
	mySession.sayHello();
	var newSession = new sessionFactory();// throw 单例类型sessionFactory不能实例化!
 */
coos.singleton = function(fn,singletonName)
{
	singletonName = singletonName || "singletonClass";
	var obj = new fn();
	var singletonClass = function()
	{
		throw new Error("单例类型" + singletonName + "不能实例化！");
	};
	singletonClass.getInstance = function(){return obj;};
	singletonClass.name = singletonName;
	return singletonClass;
};

/**
 * 定义通用的简单命令模式接口
 */
coos.command = new coos.Interface("coos.command",["execute"]);

/**
 * 定义通用的带取消操作的命令模式接口
 */
coos.undocommand = new coos.Interface("coos.undocommand",["execute","undo"]);

/**
 * aop 的实现
 * @param object 必须为对象，不能是方法本身
 * @example
 function aopTest()
{
    this.say1 =  function(s)
	{
        alert(s);
    };
    this.say2 =  function(s)
	{
        alert(s);
    };  
}
   
function beforeHander()
{
    alert("aspect said:");
}
function afterHander()
{
	alert("said by aspect");
}
  

var test = new aopTest();
coos.aop(test);
test.before("say1",beforeHander); 
test.after("say1",afterHander);
test.say1("hello I'm say1");

test.before("say2",beforeHander);
test.after("say2",afterHander);
test.say2("hello I'm say2");
 */
coos.aop = function(object)
{
	if(typeof(object) != "object")
	{
		throw new Error("传入的对象类型必须为object！");
		return false;
	}
	object.yield = null;
	object.rv = {};
	object.before  = function(method, f)
	{
		var original = eval("this." + method);
		this[method] = function()
		{
		  f.apply(this, arguments);
		  return original.apply(this, arguments);
		};
	};   
	object.after = function(method, f)
	{
	    var original = eval("this." + method);
	    this[method] = function()
	    {
	      this.rv[method] = original.apply(this, arguments);
	      return f.apply(this, arguments);
	    };
	};   
	object.around = function(method, f)
	{
    	var original = eval("this." + method);
    	this[method] = function()
	    {
	      this.yield = original;
	      return f.apply(this, arguments);
	    };
	};
};

/**
 * 采用prototype的Object扩展方法
 * @param obj 需要判断的对象
 */
coos.extend(Object, {
	extend : function(destination, source) {
	  for (var property in source)
	    destination[property] = source[property];
	  return destination;
	},
	toJSON: function(object) {
    var type = typeof object;
    switch (type) {
      case 'undefined':
      case 'function':
      case 'unknown': return;
      case 'boolean': return object.toString();
    }

    if (object === null) return 'null';
    if (object.toJSON) return object.toJSON();
    if (Object.isElement(object)) return;

    var results = [];
    for (var property in object) {
      var value = Object.toJSON(object[property]);
      if (!Object.isUndefined(value))
        results.push(property.toJSON() + ': ' + value);
    }
    return '{' + results.join(', ') + '}';
  },
  keys: function(object) {
    var keys = [];
    for (var property in object)
      keys.push(property);
    return keys;
  },
  values: function(object) {
    var values = [];
    for (var property in object)
      values.push(object[property]);
    return values;
  },
  clone: function(object) {
    return Object.extend({ }, object);
  },
  isElement: function(object) {
    return object && object.nodeType == 1;
  },
  isArray: function(object) {
  	//判断是否为数组，考虑到多种情况
  	return Object.prototype.toString.call(object) === '[object Array]';
    //return object != null && typeof object == "object" && 'splice' in object && 'join' in object;
  },
  isHash: function(object) {
    return object instanceof Hash;
  },
  isFunction: function(object) {
    return typeof object == "function";
  },
  isString: function(object) {
    return typeof object == "string";
  },
  isNumber: function(object) {
    return typeof object == "number";
  },
  isUndefined: function(object) {
    return typeof object == "undefined";
  }
});

/**
 * json的处理函数
 * parse函数把json字符串转换成对象
 * toJSONString把对象转换成json字符串(包括普通对象和json对象)
 */
coos.json = {
	parse : function(data)
	{
		if(typeof(data) != "object")
		{
			data = eval('(' + data + ')');
		}
		return data;
	},
	toJSONString : function(obj)
	{
		switch(typeof(obj))
		{
			case "object" :
			{
				var result = [];
				if(obj instanceof Array)
				{
					var len = obj.length;
					for(var i = 0; i < len; i++)
					{
						result.push(coos.json.toJSONString(obj[i]));
					}
					return "[" + result.toString(",") + "]";
				}
				else if(obj instanceof RegExp)
				{
					return obj.toString();
				}
				else
				{
					for(var attribute in obj)
					{
						result.push(attribute + ":" + coos.json.toJSONString(obj[attribute]));
					}
					return "{" + result.join(",") + "}";
				}
			}
			case "function":
			{
				return "function(){}";
			}
			case "number":
			{
				return obj.toString();
			}
			case "boolean":
			{
				return obj.toString();
			}
			case "string":
			{
				return "\"" + obj.replace(/(\\|\")/g, "\\$1").replace(/\n|\r|\t/g,function(a){return ("\n" == a) ? "\\n":("\r" == a) ? "\\r":("\t" == a) ? "\\t":"";}) + "\"";
			}
			default:
			{
				return obj.toString();
			}
		}
	}
};

/**
 * browser userAgent
 */
coos.userAgent = navigator.userAgent.toLowerCase();
/**
 * Figure out what browser is being used 
 * typeof(window.external.max_version) in some ie7.0 is unkonwn not undefined
 * @example 
if(coos.browser.msie){alert("ie browser "+"version="+ coos.browser.version);}
if(coos.browser.maxthon){alert("maxthon browser "+"version="+ coos.browser.maxthonVersion);};
alert(coos.browser.maxthon + " maxthon browser "+"version= "+ coos.browser.maxthonVersion);
 */
coos.browser = {
	version: (coos.userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
	safari: /webkit/.test(coos.userAgent) &&  !/chrome/.test(coos.userAgent),
	chrome: /chrome/.test(coos.userAgent),
	opera: /opera/.test(coos.userAgent),
	msie: /msie/.test(coos.userAgent) && !/opera/.test(coos.userAgent),
	firefox: /firefox/.test(coos.userAgent),
	mozilla: /mozilla/.test(coos.userAgent) && !/(compatible|webkit)/.test(coos.userAgent),
	maxthon: (window.external && (typeof(window.external.max_version) == "string"))?true:false,
	maxthonVersion: (window.external && (typeof(window.external.max_version) == "string"))?window.external.max_version.substr(0,1):undefined
};

/**
 * 简单的兼容浏览器的onload事件绑定
 * @param fn 需要绑定window.onload后执行的function
 */
coos.onloadEvent = function(fn)
{
	if (window.addEventListener) 
	{
		window.addEventListener("load",fn,false);
	}
	else if(window.attachEvent)
	{
		window.attachEvent("onload", fn);
	}
	else
	{
		window.onload = fn;
	}
};
